package com.igroupes.ovineherd.controller;

import cn.hutool.core.lang.ParameterizedTypeImpl;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.json.JSONObject;
import com.igroupes.ovineherd.aop.LoginUser;
import com.igroupes.ovineherd.dto.UserInfo;
import com.igroupes.ovineherd.dto.request.ModelOrderRequest;
import com.igroupes.ovineherd.model.dto.RelationshipRequest;
import com.igroupes.ovineherd.dto.request.VersionRequest;
import com.igroupes.ovineherd.dto.response.ModelDataJsonListResponse;
import com.igroupes.ovineherd.dto.response.ModelDataTableAndRelationshipListResponse;
import com.igroupes.ovineherd.dto.response.RelationshipResponse;
import com.igroupes.ovineherd.model.IParentModelData;
import com.igroupes.ovineherd.model.ModelData;
import com.igroupes.ovineherd.model.dto.ModelVersionResponse;
import com.igroupes.ovineherd.model.dto.ModelDataAddRequest;
import com.igroupes.ovineherd.model.enums.BeanTypeKey;
import com.igroupes.ovineherd.model.table.TableAttribute;
import com.igroupes.ovineherd.raw.service.IDataModelRelationshipService;
import com.igroupes.ovineherd.raw.service.IModelService;
import com.igroupes.ovineherd.service.AppService;
import com.igroupes.ovineherd.util.ExceptionUtils;
import com.igroupes.ovineherd.util.Requires;
import com.igroupes.ovineherd.vo.ResultVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 数据模型
 */
@SuppressWarnings("ALL")
@RestController
@RequestMapping("model/v2")
@LoginUser
public class ModelV2Controller {

    @Autowired
    private IModelService modelService;
    @Autowired
    private IDataModelRelationshipService dataModelRelationshipService;
    @Autowired
    private AppService appService;

    /**
     * 模型模板列表（v3）
     */
    @GetMapping("template")
    public ResultVO<ModelData> getFieldTemplate() {
        return ResultVO.success(modelService.getFieldTemplate());
    }

    /**
     * 模型排序
     * @param modelOrderRequests
     * @param userInfo
     * @return
     */
    @PutMapping("sort")
    public ResultVO<Boolean> order(@Valid @RequestBody List<ModelOrderRequest> modelOrderRequests, UserInfo userInfo){
        return ResultVO.success(modelService.order(modelOrderRequests, userInfo));
    }

    /**
     * 历史版本列表（v3）
     * @return
     */
    @GetMapping("version")
    public ResultVO<List<ModelVersionResponse>> getVersionList(UserInfo userInfo) {
        return ResultVO.success(modelService.getVersionList(userInfo.getId()));
    }

    /**
     * 版本发布（v3）
     * @return
     */
    @PostMapping("version")
    public ResultVO<Boolean> publish(UserInfo userInfo) {
        return ResultVO.success(modelService.publish(userInfo.getId()));
    }

    /**
     * 版本回退（v3）
     * @return
     */
    @PutMapping("version/rollback/{versionId}")
    public ResultVO<Boolean> rollback(UserInfo userInfo, @PathVariable("versionId") Long versionId) {
        return ResultVO.success(modelService.rollback(userInfo.getId(), versionId));
    }

    /**
     * 模型关系提交（v3）
     * @param dataModelFieldBatchTableRequest
     * @return
     */
    @PostMapping("relation")
    public ResultVO<Boolean> modelBatchAddRelationship(@Valid @RequestBody @NotEmpty(message = "传值不能为空")
                                                                   List<RelationshipRequest> relationshipRequests, UserInfo userInfo){
        return ResultVO.success(dataModelRelationshipService.modelBatchAddRelationship(relationshipRequests, userInfo));
    }

    /**
     * 模型关系列表（v3）
     * @return
     */
    @GetMapping("relation")
    public ResultVO<List<RelationshipResponse>> getRelationship(UserInfo userInfo) {
        return ResultVO.success(dataModelRelationshipService.getRelationship(userInfo));
    }

    /**
     * 模型和关系列表（v3）
     * @param userInfo
     * @return
     */
    @GetMapping("table/relation")
    public ResultVO<ModelDataTableAndRelationshipListResponse> getTableAndRelationship(UserInfo userInfo){
        return ResultVO.success(new ModelDataTableAndRelationshipListResponse(
                    modelService.tableListV2(userInfo.getId()),
                    dataModelRelationshipService.getRelationship(userInfo)
                ));
    }
    /**
     * 发布版本模型列表（v3）
     *
     * @return
     */
    @GetMapping("publish/table")
    public ResultVO<List<ModelDataJsonListResponse>> tablePublishList(UserInfo userInfo) {
        return ResultVO.success(modelService.tablePublishListV2(userInfo.getId()));
    }
    /**
     * 新增模型（v3）
     *
     * @param modelDataAddRequest
     * @return
     */
    @PostMapping("table")
    public ResultVO<Boolean> modelAdd(@RequestBody ModelDataAddRequest modelDataAddRequest, UserInfo userInfo) {
        return ResultVO.success(modelService.modelAdd(modelDataAddRequest, userInfo.getId()));
    }

    /**
     * 模型列表（v3）
     *
     * @return
     */
    @GetMapping("table")
    public ResultVO<List<ModelDataJsonListResponse>> tableList(UserInfo userInfo) {
        return ResultVO.success(modelService.tableListV2(userInfo.getId()));
    }

    /**
     * 模型详情（v3）
     *
     * @return
     */
    @GetMapping("table/{tableId}")
    public ResultVO<ModelDataJsonListResponse> tableInfo(@PathVariable @NotNull(message = "参数不能为空") Long tableId, UserInfo userInfo) {
        appService.checkUserModel(userInfo.getId(), tableId.longValue());
        return ResultVO.success(modelService.tableInfo(tableId));
    }

    /**
     * 删除模型（v3）
     *
     * @param tableId
     * @return
     */
    @DeleteMapping("table/{tableId}")
    public ResultVO<Boolean> modelDelete(@PathVariable @NotNull(message = "参数不能为空") Long tableId, UserInfo userInfo) {
        appService.checkUserModel(userInfo.getId(), tableId.longValue());
        return ResultVO.success(modelService.modelDelete(tableId, userInfo.getId()));
    }

    /**
     * 编辑模型配置(v3)
     *
     * @param table
     * @return
     */
    @PutMapping("table/{tableId}")
    public ResultVO<Boolean> tableEdit(@RequestBody @NotNull(message = "表配置不能为空")
                                               TableAttribute table, @PathVariable @NotNull(message = "参数不能为空") Long tableId, UserInfo userInfo) {
        appService.checkUserModel(userInfo.getId(), tableId.longValue());
        return ResultVO.success(modelService.tableEdit(table, tableId, userInfo.getId()));
    }

    /**
     * 新增模型字段(v3)
     *
     * @param field
     * @return
     */
    @PostMapping("table/{tableId}/field")
    public ResultVO<Boolean> fieldAdd(@RequestBody @NotNull(message = "字段不能为空") JSONObject field, @PathVariable @NotNull(message = "参数不能为空") Long tableId, UserInfo userInfo) {
        appService.checkUserModel(userInfo.getId(), tableId.longValue());
        return ResultVO.success(modelService.fieldAddV2(jsonToIParentModelData(field), tableId, userInfo.getId()));
    }

    /**
     * 新增模型字段批量(v3)
     *
     * @param field
     * @return
     */
    @PostMapping("table/{tableId}/fields")
    public ResultVO<Boolean> fieldsAdd(@RequestBody @NotNull(message = "字段不能为空") List<JSONObject> field, @PathVariable @NotNull(message = "参数不能为空") Long tableId, UserInfo userInfo) {
        appService.checkUserModel(userInfo.getId(), tableId.longValue());
        return ResultVO.success(modelService.fieldsAdd(jsonListToIParentModelData(field), tableId, userInfo.getId()));
    }

    private IParentModelData jsonToIParentModelData(JSONObject json) {
        try {
            Requires.requireNonNull(json, "json is null");
            String beanType = json.getStr("beanType");
            Map<String, BeanTypeKey> enumMap = EnumUtil.getEnumMap(BeanTypeKey.class);
            Class<?> classes = Class.forName(enumMap.get(beanType.toUpperCase()).getBean());
            return json.toBean(new ParameterizedTypeImpl(new Type[]{classes}, IParentModelData.class, IParentModelData.class));
        } catch (ClassNotFoundException ex) {
            ExceptionUtils.rethrow(ex);
            return null;
        }
    }

    private List<IParentModelData> jsonListToIParentModelData(List<JSONObject> jsons) {

        Map<String, BeanTypeKey> enumMap = EnumUtil.getEnumMap(BeanTypeKey.class);
        List<IParentModelData> iParentModelDatas = new ArrayList<>();
        for (JSONObject json
                : jsons
        ) {
            Requires.requireNonNull(json, "json is null");
            String beanType = json.getStr("beanType");
            try {
                Class<?> classes = Class.forName(enumMap.get(beanType.toUpperCase()).getBean());
                iParentModelDatas.add(json.toBean(new ParameterizedTypeImpl(new Type[]{classes}, IParentModelData.class, IParentModelData.class)));
            } catch (ClassNotFoundException ex) {
                ExceptionUtils.rethrow(ex);
                return null;
            }
        }
        return iParentModelDatas;

    }

    /**
     * 编辑模型字段（v3）
     *
     * @param fieldId
     * @return
     */
    @PutMapping("table/field/{fieldId}")
    @Transactional
    public ResultVO<Boolean> fieldEdit(@RequestBody @NotNull(message = "字段不能为空") JSONObject field
            , @PathVariable @NotNull(message = "参数不能为空") Long fieldId
            , UserInfo userInfo) {
        appService.checkUserModelField(userInfo.getId(), fieldId);
        return ResultVO.success(modelService.fieldEditV2(jsonToIParentModelData(field), fieldId, userInfo.getId()));
    }

    /**
     * 删除模型字段（v3）
     *
     * @param fieldId
     * @return
     */
    @DeleteMapping("table/field/{fieldId}")
    @Transactional
    public ResultVO<Boolean> fieldDelete(@PathVariable @NotNull(message = "参数不能为空") Long fieldId, UserInfo userInfo) {
        appService.checkUserModelField(userInfo.getId(), fieldId);
        return ResultVO.success(modelService.fieldDelete(fieldId, userInfo.getId()));
    }

}
